﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;

using Microsoft.VisualStudio.TestTools.UITesting;
using Microsoft.VisualStudio.TestTools.UITesting.HtmlControls;
using Microsoft.VisualStudio.TestTools.UnitTesting;

using FluentAssertions;

namespace CodeStream.Testing.WebAutomation.UnitTests
{
    [CodedUITest]
    public class UITemplateClassTests
    {
        private static Assembly m_sampleAssembly;
        private static string m_sampleUIDefinitionCode;
        private static Process m_browserProcess;  

        [ClassInitialize]
        public static void Initialize(TestContext testContext)
        {
            m_sampleUIDefinitionCode = UITemplateTestExtensions.GenerateDefinitionCode(
                Assembly.GetExecutingAssembly().GetManifestResourceStream("CodeStream.Testing.WebAutomation.UnitTests.UITemplateClassTests.xml"));
            m_sampleAssembly = UITemplateTestExtensions.CompileCode(m_sampleUIDefinitionCode, 
                new string[]
                {
                    "System.dll",
                    "System.Core.dll",
                    new Uri(Assembly.GetAssembly(typeof(CodeStream.Testing.WebAutomation.UIDefinitionPage)).CodeBase).LocalPath,
                    new Uri(Assembly.GetAssembly(typeof(Microsoft.VisualStudio.TestTools.UITesting.BrowserWindow)).CodeBase).LocalPath,
                    new Uri(Assembly.GetAssembly(typeof(Microsoft.VisualStudio.TestTools.UITest.Extension.BrowserService)).CodeBase).LocalPath
                }, 
                Path.Combine(testContext.DeploymentDirectory, testContext.FullyQualifiedTestClassName + ".dll"));

            string htmlPath = Path.Combine(testContext.DeploymentDirectory, "UITemplateClassTests.html");
            using (Stream input = Assembly.GetExecutingAssembly().GetManifestResourceStream("CodeStream.Testing.WebAutomation.UnitTests.UITemplateClassTests.html"))
                using (FileStream output = File.Create(htmlPath))
                    input.CopyTo(output);

            m_browserProcess = Process.Start("iexplore.exe", "-nomerge file://" + htmlPath);
        }

        [ClassCleanup]
        public static void Cleanup()
        {
            m_browserProcess.CloseMainWindow();
        }

        [TestInitialize]
        public void LogCodeToDebug()
        {
            Debug.WriteLine(m_sampleUIDefinitionCode);
        }
        
        [TestMethod]
        public void UITemplateClass_Verify_Page_Single_Control_By_Id()
        {
            var pageType = m_sampleAssembly.ShouldHaveType("TestNamespace.UITestPage");
            pageType.ShouldHaveProperty("SingleControlId");

            dynamic pageInstance = Activator.CreateInstance(pageType, m_browserProcess);

            HtmlDiv controlInstance = pageInstance.SingleControlId as HtmlDiv;
            controlInstance.InnerText.Should().Be("singleControl1");
        }

        [TestMethod]
        public void UITemplateClass_Verify_Page_Single_Control_By_Class()
        {
            var pageType = m_sampleAssembly.ShouldHaveType("TestNamespace.UITestPage");
            pageType.ShouldHaveProperty("SingleControlClass");

            dynamic pageInstance = Activator.CreateInstance(pageType, m_browserProcess);
            HtmlDiv controlInstance = pageInstance.SingleControlClass as HtmlDiv;
            controlInstance.InnerText.Should().Be("singleControl1");
        }

        [TestMethod]
        public void UITemplateClass_Verify_Page_Multiple_Control_By_Id()
        {
            var pageType = m_sampleAssembly.ShouldHaveType("TestNamespace.UITestPage");
            pageType.ShouldHaveProperty("MultipleControlIds");

            dynamic pageInstance = Activator.CreateInstance(pageType, m_browserProcess);

            HtmlDiv[] controlInstances = pageInstance.MultipleControlIds as HtmlDiv[];
            controlInstances.Length.Should().Be(1);
            controlInstances[0].InnerText.Should().Be("multipleControl1");
        }
    
        [TestMethod]
        public void UITemplateClass_Verify_Page_Multiple_Control_By_Class()
        {
            var pageType = m_sampleAssembly.ShouldHaveType("TestNamespace.UITestPage");
            pageType.ShouldHaveProperty("MultipleControlClasss");

            dynamic pageInstance = Activator.CreateInstance(pageType, m_browserProcess);

            HtmlDiv[] controlInstances = pageInstance.MultipleControlClasss as HtmlDiv[];
            controlInstances.Length.Should().Be(2);
            controlInstances[0].InnerText.Should().Be("multipleControl1");
            controlInstances[1].InnerText.Should().Be("multipleControl2");
        }

        [TestMethod]
        public void UITemplateClass_Verify_Page_Single_Container_By_Id()
        {
            var pageType = m_sampleAssembly.ShouldHaveType("TestNamespace.UITestPage");
            m_sampleAssembly.ShouldHaveType("TestNamespace.UISingleContainerId", typeof(HtmlDiv));
            pageType.ShouldHaveProperty("SingleContainerId");

            dynamic pageInstance = Activator.CreateInstance(pageType, m_browserProcess);

            HtmlDiv containerInstance = pageInstance.SingleContainerId as HtmlDiv;
            containerInstance.FriendlyName.Should().Be("singleContainer");
        }

        [TestMethod]
        public void UITemplateClass_Verify_Page_Single_Container_By_Class()
        {
            var pageType = m_sampleAssembly.ShouldHaveType("TestNamespace.UITestPage");
            m_sampleAssembly.ShouldHaveType("TestNamespace.UISingleContainerClass", typeof(HtmlDiv));
            pageType.ShouldHaveProperty("SingleContainerClass");
            
            dynamic pageInstance = Activator.CreateInstance(pageType, m_browserProcess);

            HtmlDiv containerInstance = pageInstance.SingleContainerClass as HtmlDiv;
            containerInstance.FriendlyName.Should().Be("singleContainer");             
        }

        [TestMethod]
        public void UITemplateClass_Verify_Page_Multiple_Container_By_Id()
        {
            var pageType = m_sampleAssembly.ShouldHaveType("TestNamespace.UITestPage");
            m_sampleAssembly.ShouldHaveType("TestNamespace.UIMultipleContainerId", typeof(HtmlDiv));
            pageType.ShouldHaveProperty("MultipleContainerIds");

            dynamic pageInstance = Activator.CreateInstance(pageType, m_browserProcess);            

            HtmlDiv[] containerInstance = pageInstance.MultipleContainerIds as HtmlDiv[];
            containerInstance.Length.Should().Be(1);
            containerInstance[0].FriendlyName.Should().Be("multipleContainer1");
        }

        [TestMethod]
        public void UITemplateClass_Verify_Page_Multiple_Container_By_Class()
        {
            var pageType = m_sampleAssembly.ShouldHaveType("TestNamespace.UITestPage");
            m_sampleAssembly.ShouldHaveType("TestNamespace.UIMultipleContainerId", typeof(HtmlDiv));
            pageType.ShouldHaveProperty("MultipleContainerClasss");

            dynamic pageInstance = Activator.CreateInstance(pageType, m_browserProcess);

            HtmlDiv[] containerInstance = pageInstance.MultipleContainerClasss as HtmlDiv[];
            containerInstance.Length.Should().Be(2);
            containerInstance[0].FriendlyName.Should().Be("multipleContainer1");
            containerInstance[1].FriendlyName.Should().Be("multipleContainer2");
        }

        [TestMethod]
        public void UITemplateClass_Verify_Container_Single_Control_By_Id()
        {
            var pageType = m_sampleAssembly.ShouldHaveType("TestNamespace.UITestPage");
            var containerType = m_sampleAssembly.ShouldHaveType("TestNamespace.UISingleContainerId", typeof(HtmlDiv));
            containerType.ShouldHaveProperty("SingleContainerId");

            dynamic pageInstance = Activator.CreateInstance(pageType, m_browserProcess);
            dynamic containerInstance = pageInstance.SingleContainerId as HtmlDiv;

            HtmlDiv controlInstance = (HtmlDiv)containerInstance.SingleControlId;
            controlInstance.InnerText.Should().Be("containedSingleControl1");
        }

        [TestMethod]
        public void UITemplateClass_Verify_Container_Single_Control_By_Class()
        {
            var pageType = m_sampleAssembly.ShouldHaveType("TestNamespace.UITestPage");
            var containerType = m_sampleAssembly.ShouldHaveType("TestNamespace.UISingleContainerId", typeof(HtmlDiv));
            containerType.ShouldHaveProperty("SingleContainerId");

            dynamic pageInstance = Activator.CreateInstance(pageType, m_browserProcess);
            dynamic containerInstance = pageInstance.SingleContainerId;

            HtmlDiv controlInstance = (HtmlDiv)containerInstance.SingleControlClass as HtmlDiv;
            controlInstance.InnerText.Should().Be("containedSingleControl1");
        }

        [TestMethod]
        public void UITemplateClass_Verify_Container_Multiple_Control_By_Id()
        {
            var pageType = m_sampleAssembly.ShouldHaveType("TestNamespace.UITestPage");
            var containerType = m_sampleAssembly.ShouldHaveType("TestNamespace.UISingleContainerId", typeof(HtmlDiv));
            containerType.ShouldHaveProperty("SingleContainerId");

            dynamic pageInstance = Activator.CreateInstance(pageType, m_browserProcess);
            dynamic containerInstance = pageInstance.SingleContainerId;

            HtmlDiv[] controlInstances = (HtmlDiv[])containerInstance.MultipleControlIds;
            controlInstances.Length.Should().Be(1);
            controlInstances[0].InnerText.Should().Be("containedMultipleControl1");
        }

        [TestMethod]
        public void UITemplateClass_Verify_Container_Multiple_Control_By_Class()
        {
            var pageType = m_sampleAssembly.ShouldHaveType("TestNamespace.UITestPage");
            var containerType = m_sampleAssembly.ShouldHaveType("TestNamespace.UISingleContainerId", typeof(HtmlDiv));
            containerType.ShouldHaveProperty("SingleContainerId");

            dynamic pageInstance = Activator.CreateInstance(pageType, m_browserProcess);
            dynamic containerInstance = pageInstance.SingleContainerId;

            HtmlDiv[] controlInstances = (HtmlDiv[])containerInstance.MultipleControlClasss;
            controlInstances.Length.Should().Be(2);
            controlInstances[0].InnerText.Should().Be("containedMultipleControl1");
            controlInstances[1].InnerText.Should().Be("containedMultipleControl2");
        }

        [TestMethod]
        public void UITemplateClass_Verify_Container_Single_Container_By_Id()
        {
            var pageType = m_sampleAssembly.ShouldHaveType("TestNamespace.UITestPage");
            var containerType = m_sampleAssembly.ShouldHaveType("TestNamespace.UISingleContainerId", typeof(HtmlDiv));
            containerType.ShouldHaveProperty("SingleContainerId");

            dynamic pageInstance = Activator.CreateInstance(pageType, m_browserProcess);
            dynamic containerInstance = pageInstance.SingleContainerId;

            HtmlDiv childContainerInstance = containerInstance.SingleContainerId as HtmlDiv;
            childContainerInstance.FriendlyName.Should().Be("containedSingleContainer");
        }

        [TestMethod]
        public void UITemplateClass_Verify_Container_Single_Container_By_Class()
        {
            var pageType = m_sampleAssembly.ShouldHaveType("TestNamespace.UITestPage");
            var containerType = m_sampleAssembly.ShouldHaveType("TestNamespace.UISingleContainerId", typeof(HtmlDiv));
            containerType.ShouldHaveProperty("SingleContainerId");

            dynamic pageInstance = Activator.CreateInstance(pageType, m_browserProcess);
            dynamic containerInstance = pageInstance.SingleContainerId;

            HtmlDiv childContainerInstance = containerInstance.SingleContainerClass as HtmlDiv;
            childContainerInstance.FriendlyName.Should().Be("containedSingleContainer");   
        }
        
        [TestMethod]
        public void UITemplateClass_Verify_Container_Multiple_Container_By_Id()
        {
            var pageType = m_sampleAssembly.ShouldHaveType("TestNamespace.UITestPage");
            var containerType = m_sampleAssembly.ShouldHaveType("TestNamespace.UISingleContainerId", typeof(HtmlDiv));
            pageType.ShouldHaveProperty("SingleContainerId");
            containerType.ShouldHaveProperty("MultipleContainerIds");

            dynamic pageInstance = Activator.CreateInstance(pageType, m_browserProcess);
            dynamic containerInstance = pageInstance.SingleContainerId;

            HtmlDiv[] childcontainerInstances = containerInstance.MultipleContainerIds as HtmlDiv[];
            childcontainerInstances.Length.Should().Be(1);
            childcontainerInstances[0].FriendlyName.Should().Be("containedMultipleContainer1");
        }

        [TestMethod]
        public void UITemplateClass_Verify_Container_Multiple_Container_By_Class()
        {
            var pageType = m_sampleAssembly.ShouldHaveType("TestNamespace.UITestPage");
            var containerType = m_sampleAssembly.ShouldHaveType("TestNamespace.UISingleContainerId", typeof(HtmlDiv));
            pageType.ShouldHaveProperty("SingleContainerId");
            containerType.ShouldHaveProperty("MultipleContainerClasss");

            dynamic pageInstance = Activator.CreateInstance(pageType, m_browserProcess);
            dynamic containerInstance = pageInstance.SingleContainerId;

            HtmlDiv[] childcontainerInstances = containerInstance.MultipleContainerClasss as HtmlDiv[];
            childcontainerInstances.Length.Should().Be(2);
            childcontainerInstances[0].FriendlyName.Should().Be("containedMultipleContainer1");
            childcontainerInstances[1].FriendlyName.Should().Be("containedMultipleContainer2");
        }        
    }
}
